package com.example.searchservice.config;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.hankcs.hanlp.corpus.io.IOUtil;
import com.hankcs.hanlp.corpus.tag.Nature;
import com.hankcs.hanlp.seg.common.Term;
import jakarta.annotation.PostConstruct;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.wltea.analyzer.core.IKSegmenter;

import java.io.*;
import java.nio.charset.StandardCharsets;

import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

@Configuration
public class IkAnalyzerConfiguration {


    @PostConstruct
    public void checkFileExists() {
        ClassPathResource resource = new ClassPathResource("data/dictionary/CoreNatureDictionary.mini.txt");
        this.createFile(resource);
        ClassPathResource customResource = new ClassPathResource("data/dictionary/custom/CustomDictionary.txt");
        this.createFile(customResource);
    }

    private void createFile(ClassPathResource resource){
        try {
            // 检查文件是否真的存在
            File file = resource.getFile();

            System.out.println("文件存在: " + file.exists());
            System.out.println("文件路径: " + file.getAbsolutePath());
            System.out.println("可读: " + file.canRead());
            System.out.println("可写: " + file.canWrite());

            if (!file.exists()) {
                // 如果文件不存在，创建目录和文件
                file.getParentFile().mkdirs();
                file.createNewFile();
                System.out.println("已创建文件");
            }
            this.manuallyCreateBinFile(file);

        } catch (Exception e) {
            System.err.println("文件检查失败: " + e.getMessage());
        }
    }

    public void manuallyCreateBinFile(File file) {
        try {
            String binPath = file.getAbsolutePath() + ".bin";

            // 读取文本文件
            List<String> lines = this.readDictionaryFile(file);
            List<String> binContent = new ArrayList<>();

            if (lines.isEmpty()) {
                System.out.println("词典文件为空或不存在");
                return;
            }

            for (String line : lines) {
                if (line.trim().isEmpty() || line.startsWith("#")) {
                    continue;
                }
                binContent.add(line);
            }

            this.createBinaryDictionary(lines, binPath);

            System.out.println("bin 文件创建成功: " + binPath);
            System.out.println("共处理 " + lines.size() + " 个词条");
            this.testBinFile(new File(binPath));

        } catch (Exception e) {
            System.err.println("手动创建bin文件失败: " + e.getMessage());
        }
    }

    /**
     * 读取词典文件内容
     */
    private List<String> readDictionaryFile(File file) throws IOException {
        List<String> lines = new ArrayList<>();

        if (!file.exists()) {
            System.out.println("词典文件不存在，创建示例文件");
            this.createSampleDictionary(file);
            // 重新尝试读取
            if (file.exists()) {
                return this.readDictionaryFile(file);
            }
            return lines;
        }

        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) {

            String line;
            while ((line = reader.readLine()) != null) {
                line = line.trim();
                // 跳过空行和注释
                if (line.isEmpty() || line.startsWith("#")) {
                    continue;
                }
                lines.add(line);
            }
        }
        return lines;
    }

    /**
     * 创建示例词典文件（如果不存在）
     */
    private void createSampleDictionary(File file) throws IOException {
        File parentDir = file.getParentFile();

        // 创建目录
        if (!parentDir.exists()) {
            parentDir.mkdirs();
        }

        // 创建文件并写入示例内容
        try (BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) {

            writer.write("# 自定义词典文件");
            writer.newLine();
            writer.write("# 格式: 词语 词性 词频");
            writer.newLine();
            writer.write("马云 n 1000");
            writer.newLine();
            writer.write("阿里巴巴 n 1000");
            writer.newLine();
            writer.write("淘宝 n 800");
            writer.newLine();
            writer.write("腾讯 n 800");
            writer.newLine();
            writer.write("京东 n 800");
        }

        System.out.println("已创建示例词典文件: " + file.getAbsolutePath());
    }

    /**
     * 测试 bin 文件是否有效
     */
    public void testBinFile(File binFile) {
        try {
           if (binFile.exists()) {
                System.out.println("bin 文件大小: " + binFile.length() + " bytes");

                // 尝试读取 bin 文件
                try (DataInputStream in = new DataInputStream(new FileInputStream(binFile))) {
                    int count = in.readInt();
                    System.out.println("bin 文件包含 " + count + " 个词条");

                    // 读取前几个词条作为示例
                    for (int i = 0; i < Math.min(3, count); i++) {
                        int length = in.readInt();
                        byte[] bytes = new byte[length];
                        in.readFully(bytes);
                        String wordEntry = new String(bytes, StandardCharsets.UTF_8);
                        System.out.println("词条 " + (i + 1) + ": " + wordEntry);
                    }
                }
            }

        } catch (Exception e) {
            System.err.println("测试 bin 文件失败: " + e.getMessage());
        }
    }


    /**
     * 创建二进制词典文件（正确的方法）
     */
    private void createBinaryDictionary(List<String> lines, String binFilePath) throws IOException {
        try (DataOutputStream out = new DataOutputStream(new FileOutputStream(binFilePath))) {
            // 写入词条数量
            out.writeInt(lines.size());

            // 写入每个词条
            for (String line : lines) {
                // 将字符串转换为字节数组并写入
                byte[] lineBytes = line.getBytes(StandardCharsets.UTF_8);
                out.writeInt(lineBytes.length); // 先写入长度
                out.write(lineBytes);           // 再写入数据
            }
        }
    }

    @Bean
    public IKSegmenter ikSegmenter() {
        // 使用默认词典
        String text = "初始化文本";
        StringReader reader = new StringReader(text);
        return new IKSegmenter(reader, true); // true表示使用智能分词
    }

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
//        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);

        SimpleModule module = new SimpleModule();
        module.addSerializer(Nature.class, new NatureSerializer());
        module.addSerializer(Term.class, new TermSerializer());
        objectMapper.registerModule(module);

        return objectMapper;
    }

    class NatureSerializer extends JsonSerializer<Nature> {
        @Override
        public void serialize(Nature value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            // 将 Nature 对象序列化为其字符串形式
            gen.writeString(value.toString());
        }
    }

    class TermSerializer extends JsonSerializer<Term> {
        @Override
        public void serialize(Term term, JsonGenerator gen, SerializerProvider serializers)
                throws IOException {
            gen.writeStartObject();
            gen.writeStringField("word", term.word);
            gen.writeStringField("nature", term.nature.toString());
            // 可以添加其他需要序列化的字段
            gen.writeNumberField("offset", term.offset);
            gen.writeNumberField("length", term.length());
            gen.writeEndObject();
        }
    }
}